{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "d7f10b19-c061-42b2-8b42-e3cbafa3b1da",
   "metadata": {},
   "source": [
    "# Fine-Tune FLAN-T5 with Reinforcement Learning (PPO) and PEFT to Generate Less-Toxic Summaries"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "36ef668a-9c51-489b-be47-a07a09ef2289",
   "metadata": {},
   "source": [
    "In this notebook, you will fine-tune a FLAN-T5 model to generate less toxic content with Meta AI's hate speech reward model. The reward model is a binary classifier that predicts either \"not hate\" or \"hate\" for the given text. You will use Proximal Policy Optimization (PPO) to fine-tune and reduce the model's toxicity."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ed5003e2-a642-416b-bd3f-93fb339c3a7d",
   "metadata": {
    "tags": []
   },
   "source": [
    "# Table of Contents"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6791f449-d1da-461b-9eb7-c6dc6b37b15c",
   "metadata": {
    "tags": []
   },
   "source": [
    "- [ 1 - Set up Kernel and Required Dependencies](#1)\n",
    "- [ 2 - Load FLAN-T5 Model, Prepare Reward Model and Toxicity Evaluator](#2)\n",
    "  - [ 2.1 - Load Data and FLAN-T5 Model Fine-Tuned with Summarization Instruction](#2.1)\n",
    "  - [ 2.2 - Prepare Reward Model](#2.2)\n",
    "  - [ 2.3 - Evaluate Toxicity](#2.3)\n",
    "- [ 3 - Perform Fine-Tuning to Detoxify the Summaries](#3)\n",
    "  - [ 3.1 - Initialize `PPOTrainer`](#3.1)\n",
    "  - [ 3.2 - Fine-Tune the Model](#3.2)\n",
    "  - [ 3.3 - Evaluate the Model Quantitatively](#3.3)\n",
    "  - [ 3.4 - Evaluate the Model Qualitatively](#3.4)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "89f973f1-f095-4915-86d0-bc16380da22d",
   "metadata": {
    "tags": []
   },
   "source": [
    "<a name='1'></a>\n",
    "## 1 - Set up Kernel and Required Dependencies"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ba0923b1-daaa-437c-a604-455d839b9877",
   "metadata": {
    "tags": []
   },
   "source": [
    "First, check that the correct kernel is chosen.\n",
    "\n",
    "<img src=\"images/kernel_set_up.png\" width=\"300\"/>\n",
    "\n",
    "You can click on that (top right of the screen) to see and check the details of the image, kernel, and instance type.\n",
    "\n",
    "<img src=\"images/w3_kernel_and_instance_type.png\" width=\"600\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5e38b387-d92d-4361-8112-37c908f25ff1",
   "metadata": {
    "tags": []
   },
   "source": [
    "Now install the required packages to use PyTorch and Hugging Face transformers and datasets.\n",
    "\n",
    "<img src=\"\" alt=\"Time alert open medium\"/>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "f9d24e86-f76f-4a44-90ef-0777752075a8",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: pip in /opt/conda/lib/python3.7/site-packages (23.1.2)\n",
      "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n",
      "\u001b[0mNote: you may need to restart the kernel to use updated packages.\n",
      "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n",
      "\u001b[0mNote: you may need to restart the kernel to use updated packages.\n",
      "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n",
      "\u001b[0mNote: you may need to restart the kernel to use updated packages.\n",
      "Collecting git+https://github.com/lvwerra/trl.git@25fa1bd\n",
      "  Cloning https://github.com/lvwerra/trl.git (to revision 25fa1bd) to /tmp/pip-req-build-n6xazgh2\n",
      "  Running command git clone --filter=blob:none --quiet https://github.com/lvwerra/trl.git /tmp/pip-req-build-n6xazgh2\n",
      "\u001b[33m  WARNING: Did not find branch or tag '25fa1bd', assuming revision or ref.\u001b[0m\u001b[33m\n",
      "\u001b[0m  Running command git checkout -q 25fa1bd\n",
      "  Resolved https://github.com/lvwerra/trl.git to commit 25fa1bd\n",
      "  Preparing metadata (setup.py) ... \u001b[?25ldone\n",
      "\u001b[?25hRequirement already satisfied: torch>=1.4.0 in /opt/conda/lib/python3.7/site-packages (from trl==0.4.2.dev0) (1.13.1)\n",
      "Requirement already satisfied: transformers>=4.18.0 in /opt/conda/lib/python3.7/site-packages (from trl==0.4.2.dev0) (4.27.2)\n",
      "Requirement already satisfied: numpy>=1.18.2 in /opt/conda/lib/python3.7/site-packages (from trl==0.4.2.dev0) (1.21.6)\n",
      "Requirement already satisfied: accelerate in /opt/conda/lib/python3.7/site-packages (from trl==0.4.2.dev0) (0.20.3)\n",
      "Requirement already satisfied: datasets in /opt/conda/lib/python3.7/site-packages (from trl==0.4.2.dev0) (2.11.0)\n",
      "Requirement already satisfied: typing-extensions in /opt/conda/lib/python3.7/site-packages (from torch>=1.4.0->trl==0.4.2.dev0) (4.6.3)\n",
      "Requirement already satisfied: nvidia-cuda-runtime-cu11==11.7.99 in /opt/conda/lib/python3.7/site-packages (from torch>=1.4.0->trl==0.4.2.dev0) (11.7.99)\n",
      "Requirement already satisfied: nvidia-cudnn-cu11==8.5.0.96 in /opt/conda/lib/python3.7/site-packages (from torch>=1.4.0->trl==0.4.2.dev0) (8.5.0.96)\n",
      "Requirement already satisfied: nvidia-cublas-cu11==11.10.3.66 in /opt/conda/lib/python3.7/site-packages (from torch>=1.4.0->trl==0.4.2.dev0) (11.10.3.66)\n",
      "Requirement already satisfied: nvidia-cuda-nvrtc-cu11==11.7.99 in /opt/conda/lib/python3.7/site-packages (from torch>=1.4.0->trl==0.4.2.dev0) (11.7.99)\n",
      "Requirement already satisfied: setuptools in /opt/conda/lib/python3.7/site-packages (from nvidia-cublas-cu11==11.10.3.66->torch>=1.4.0->trl==0.4.2.dev0) (65.5.1)\n",
      "Requirement already satisfied: wheel in /opt/conda/lib/python3.7/site-packages (from nvidia-cublas-cu11==11.10.3.66->torch>=1.4.0->trl==0.4.2.dev0) (0.40.0)\n",
      "Requirement already satisfied: filelock in /opt/conda/lib/python3.7/site-packages (from transformers>=4.18.0->trl==0.4.2.dev0) (3.0.12)\n",
      "Requirement already satisfied: huggingface-hub<1.0,>=0.11.0 in /opt/conda/lib/python3.7/site-packages (from transformers>=4.18.0->trl==0.4.2.dev0) (0.15.1)\n",
      "Requirement already satisfied: packaging>=20.0 in /opt/conda/lib/python3.7/site-packages (from transformers>=4.18.0->trl==0.4.2.dev0) (23.1)\n",
      "Requirement already satisfied: pyyaml>=5.1 in /opt/conda/lib/python3.7/site-packages (from transformers>=4.18.0->trl==0.4.2.dev0) (6.0)\n",
      "Requirement already satisfied: regex!=2019.12.17 in /opt/conda/lib/python3.7/site-packages (from transformers>=4.18.0->trl==0.4.2.dev0) (2023.6.3)\n",
      "Requirement already satisfied: requests in /opt/conda/lib/python3.7/site-packages (from transformers>=4.18.0->trl==0.4.2.dev0) (2.31.0)\n",
      "Requirement already satisfied: tokenizers!=0.11.3,<0.14,>=0.11.1 in /opt/conda/lib/python3.7/site-packages (from transformers>=4.18.0->trl==0.4.2.dev0) (0.13.3)\n",
      "Requirement already satisfied: tqdm>=4.27 in /opt/conda/lib/python3.7/site-packages (from transformers>=4.18.0->trl==0.4.2.dev0) (4.65.0)\n",
      "Requirement already satisfied: importlib-metadata in /opt/conda/lib/python3.7/site-packages (from transformers>=4.18.0->trl==0.4.2.dev0) (6.6.0)\n",
      "Requirement already satisfied: psutil in /opt/conda/lib/python3.7/site-packages (from accelerate->trl==0.4.2.dev0) (5.6.7)\n",
      "Requirement already satisfied: pyarrow>=8.0.0 in /opt/conda/lib/python3.7/site-packages (from datasets->trl==0.4.2.dev0) (12.0.1)\n",
      "Requirement already satisfied: dill<0.3.7,>=0.3.0 in /opt/conda/lib/python3.7/site-packages (from datasets->trl==0.4.2.dev0) (0.3.6)\n",
      "Requirement already satisfied: pandas in /opt/conda/lib/python3.7/site-packages (from datasets->trl==0.4.2.dev0) (1.3.5)\n",
      "Requirement already satisfied: xxhash in /opt/conda/lib/python3.7/site-packages (from datasets->trl==0.4.2.dev0) (3.2.0)\n",
      "Requirement already satisfied: multiprocess in /opt/conda/lib/python3.7/site-packages (from datasets->trl==0.4.2.dev0) (0.70.14)\n",
      "Requirement already satisfied: fsspec[http]>=2021.11.1 in /opt/conda/lib/python3.7/site-packages (from datasets->trl==0.4.2.dev0) (2023.1.0)\n",
      "Requirement already satisfied: aiohttp in /opt/conda/lib/python3.7/site-packages (from datasets->trl==0.4.2.dev0) (3.8.4)\n",
      "Requirement already satisfied: responses<0.19 in /opt/conda/lib/python3.7/site-packages (from datasets->trl==0.4.2.dev0) (0.18.0)\n",
      "Requirement already satisfied: attrs>=17.3.0 in /opt/conda/lib/python3.7/site-packages (from aiohttp->datasets->trl==0.4.2.dev0) (23.1.0)\n",
      "Requirement already satisfied: charset-normalizer<4.0,>=2.0 in /opt/conda/lib/python3.7/site-packages (from aiohttp->datasets->trl==0.4.2.dev0) (2.0.4)\n",
      "Requirement already satisfied: multidict<7.0,>=4.5 in /opt/conda/lib/python3.7/site-packages (from aiohttp->datasets->trl==0.4.2.dev0) (6.0.4)\n",
      "Requirement already satisfied: async-timeout<5.0,>=4.0.0a3 in /opt/conda/lib/python3.7/site-packages (from aiohttp->datasets->trl==0.4.2.dev0) (4.0.2)\n",
      "Requirement already satisfied: yarl<2.0,>=1.0 in /opt/conda/lib/python3.7/site-packages (from aiohttp->datasets->trl==0.4.2.dev0) (1.9.2)\n",
      "Requirement already satisfied: frozenlist>=1.1.1 in /opt/conda/lib/python3.7/site-packages (from aiohttp->datasets->trl==0.4.2.dev0) (1.3.3)\n",
      "Requirement already satisfied: aiosignal>=1.1.2 in /opt/conda/lib/python3.7/site-packages (from aiohttp->datasets->trl==0.4.2.dev0) (1.3.1)\n",
      "Requirement already satisfied: asynctest==0.13.0 in /opt/conda/lib/python3.7/site-packages (from aiohttp->datasets->trl==0.4.2.dev0) (0.13.0)\n",
      "Requirement already satisfied: idna<4,>=2.5 in /opt/conda/lib/python3.7/site-packages (from requests->transformers>=4.18.0->trl==0.4.2.dev0) (2.8)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/conda/lib/python3.7/site-packages (from requests->transformers>=4.18.0->trl==0.4.2.dev0) (2.0.3)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /opt/conda/lib/python3.7/site-packages (from requests->transformers>=4.18.0->trl==0.4.2.dev0) (2023.5.7)\n",
      "Requirement already satisfied: zipp>=0.5 in /opt/conda/lib/python3.7/site-packages (from importlib-metadata->transformers>=4.18.0->trl==0.4.2.dev0) (2.2.0)\n",
      "Requirement already satisfied: python-dateutil>=2.7.3 in /opt/conda/lib/python3.7/site-packages (from pandas->datasets->trl==0.4.2.dev0) (2.8.2)\n",
      "Requirement already satisfied: pytz>=2017.3 in /opt/conda/lib/python3.7/site-packages (from pandas->datasets->trl==0.4.2.dev0) (2019.3)\n",
      "Requirement already satisfied: six>=1.5 in /opt/conda/lib/python3.7/site-packages (from python-dateutil>=2.7.3->pandas->datasets->trl==0.4.2.dev0) (1.14.0)\n",
      "Building wheels for collected packages: trl\n",
      "  Building wheel for trl (setup.py) ... \u001b[?25ldone\n",
      "\u001b[?25h  Created wheel for trl: filename=trl-0.4.2.dev0-py3-none-any.whl size=67536 sha256=46b11e0c035a1d0affa8cc8a8484e130510d2d6c027e953e829ce75cea1deb1c\n",
      "  Stored in directory: /tmp/pip-ephem-wheel-cache-04oci3ac/wheels/41/26/75/08a45cee1a1bba06c4f340451483cdfe150f4c8dad3876fb2e\n",
      "Successfully built trl\n",
      "Installing collected packages: trl\n",
      "Successfully installed trl-0.4.2.dev0\n",
      "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n",
      "\u001b[0mNote: you may need to restart the kernel to use updated packages.\n"
     ]
    }
   ],
   "source": [
    "%pip install --upgrade pip\n",
    "%pip install --disable-pip-version-check \\\n",
    "    torch==1.13.1 \\\n",
    "    torchdata==0.5.1 --quiet\n",
    "\n",
    "%pip install \\\n",
    "    transformers==4.27.2 \\\n",
    "    datasets==2.11.0 \\\n",
    "    evaluate==0.4.0 \\\n",
    "    rouge_score==0.1.2 \\\n",
    "    peft==0.3.0 --quiet\n",
    "\n",
    "# Installing the Reinforcement Learning library directly from github.\n",
    "%pip install git+https://github.com/lvwerra/trl.git@25fa1bd    "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b8f3c076-d9d2-40e3-b005-9dd66b5a163a",
   "metadata": {
    "tags": []
   },
   "source": [
    "<img src=\"\" alt=\"Time alert close\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "74bfd06e-c747-43e0-b86c-0398628e1c32",
   "metadata": {
    "tags": []
   },
   "source": [
    "Import the necessary components. Some of them are new for this week, they will be discussed later in the notebook. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "d8c20bed-6a30-4847-a507-02969ecb4465",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "from transformers import pipeline, AutoTokenizer, AutoModelForSequenceClassification, AutoModelForSeq2SeqLM, GenerationConfig\n",
    "from datasets import load_dataset\n",
    "from peft import PeftModel, PeftConfig, LoraConfig, TaskType\n",
    "\n",
    "# trl: Transformer Reinforcement Learning library\n",
    "from trl import PPOTrainer, PPOConfig, AutoModelForSeq2SeqLMWithValueHead\n",
    "from trl import create_reference_model\n",
    "from trl.core import LengthSampler\n",
    "\n",
    "import torch\n",
    "import evaluate\n",
    "\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "# tqdm library makes the loops show a smart progress meter.\n",
    "from tqdm import tqdm\n",
    "tqdm.pandas()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b76eea84-8e3a-4487-9692-613977e6c8e3",
   "metadata": {},
   "source": [
    "<a name='2'></a>\n",
    "## 2 - Load FLAN-T5 Model, Prepare Reward Model and Toxicity Evaluator"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4a5f97d4-ea5f-4072-b5d6-785d1d833ed4",
   "metadata": {
    "tags": []
   },
   "source": [
    "<a name='2.1'></a>\n",
    "### 2.1 - Load Data and FLAN-T5 Model Fine-Tuned with Summarization Instruction"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "90dc0211-4032-4967-946d-3a538829d5c9",
   "metadata": {
    "tags": []
   },
   "source": [
    "You will keep working with the same Hugging Face dataset [DialogSum](https://huggingface.co/datasets/knkarthick/dialogsum) and the pre-trained model [FLAN-T5](https://huggingface.co/docs/transformers/model_doc/flan-t5). "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "b058b52b-ec4d-4426-8d71-91e898f727f6",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "e312f456bbd143479da913cc29acef38",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading readme:   0%|          | 0.00/4.56k [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading and preparing dataset csv/knkarthick--dialogsum to /root/.cache/huggingface/datasets/knkarthick___csv/knkarthick--dialogsum-391706c81424fc80/0.0.0/6954658bab30a358235fa864b05cf819af0e179325c740e4bc853bcc7ec513e1...\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "6fd9b9377355457485759d9822eb6645",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading data files:   0%|          | 0/3 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "7dc4077678e84e01a0b6b181d9e346aa",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading data:   0%|          | 0.00/11.3M [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "4f08d76cd742486ca7376dac840bc93b",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading data:   0%|          | 0.00/1.35M [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "5784f48aa2214a70854d745ae0cd42db",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading data:   0%|          | 0.00/442k [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "b9e172e51eb749cf8d9e31d104b8c5a3",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Extracting data files:   0%|          | 0/3 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Generating train split: 0 examples [00:00, ? examples/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Generating test split: 0 examples [00:00, ? examples/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Generating validation split: 0 examples [00:00, ? examples/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Dataset csv downloaded and prepared to /root/.cache/huggingface/datasets/knkarthick___csv/knkarthick--dialogsum-391706c81424fc80/0.0.0/6954658bab30a358235fa864b05cf819af0e179325c740e4bc853bcc7ec513e1. Subsequent calls will reuse this data.\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "4c791e83f9f645419f4c06dd0ad2736f",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "  0%|          | 0/3 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "DatasetDict({\n",
       "    train: Dataset({\n",
       "        features: ['id', 'dialogue', 'summary', 'topic'],\n",
       "        num_rows: 12460\n",
       "    })\n",
       "    test: Dataset({\n",
       "        features: ['id', 'dialogue', 'summary', 'topic'],\n",
       "        num_rows: 1500\n",
       "    })\n",
       "    validation: Dataset({\n",
       "        features: ['id', 'dialogue', 'summary', 'topic'],\n",
       "        num_rows: 500\n",
       "    })\n",
       "})"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model_name=\"google/flan-t5-base\"\n",
    "huggingface_dataset_name = \"knkarthick/dialogsum\"\n",
    "\n",
    "dataset_original = load_dataset(huggingface_dataset_name)\n",
    "\n",
    "dataset_original"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "668d30d6-6f81-4e52-a81a-3057163ddb0e",
   "metadata": {},
   "source": [
    "The next step will be to preprocess the dataset. You will take only a part of it, then filter the dialogues of a particular length (just to make those examples long enough and, at the same time, easy to read). Then wrap each dialogue with the instruction and tokenize the prompts. Save the token ids in the field `input_ids` and decoded version of the prompts in the field `query`.\n",
    "\n",
    "You could do that all step by step in the cell below, but it is a good habit to organize that all in a function `build_dataset`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "51469abe-4d72-4093-a6c6-8e04e19f09eb",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Found cached dataset csv (/root/.cache/huggingface/datasets/knkarthick___csv/knkarthick--dialogsum-391706c81424fc80/0.0.0/6954658bab30a358235fa864b05cf819af0e179325c740e4bc853bcc7ec513e1)\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Filter:   0%|          | 0/12460 [00:00<?, ? examples/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "571832fed43a4d3db1f093e07a53ea09",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading (…)okenizer_config.json:   0%|          | 0.00/2.54k [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "8824ffaa5b3c44d7bb1baf08dd50058b",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading spiece.model:   0%|          | 0.00/792k [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "1cf5ab648c624d7c949186b805ba8b40",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading (…)/main/tokenizer.json:   0%|          | 0.00/2.42M [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "4764a4d35bd14d6f9ca736820ab0c2cb",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading (…)cial_tokens_map.json:   0%|          | 0.00/2.20k [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Map:   0%|          | 0/10022 [00:00<?, ? examples/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "DatasetDict({\n",
      "    train: Dataset({\n",
      "        features: ['id', 'dialogue', 'summary', 'topic', 'input_ids', 'query'],\n",
      "        num_rows: 8017\n",
      "    })\n",
      "    test: Dataset({\n",
      "        features: ['id', 'dialogue', 'summary', 'topic', 'input_ids', 'query'],\n",
      "        num_rows: 2005\n",
      "    })\n",
      "})\n"
     ]
    }
   ],
   "source": [
    "def build_dataset(model_name,\n",
    "                  dataset_name,\n",
    "                  input_min_text_length, \n",
    "                  input_max_text_length):\n",
    "\n",
    "    \"\"\"\n",
    "    Preprocess the dataset and split it into train and test parts.\n",
    "\n",
    "    Parameters:\n",
    "    - model_name (str): Tokenizer model name.\n",
    "    - dataset_name (str): Name of the dataset to load.\n",
    "    - input_min_text_length (int): Minimum length of the dialogues.\n",
    "    - input_max_text_length (int): Maximum length of the dialogues.\n",
    "        \n",
    "    Returns:\n",
    "    - dataset_splits (datasets.dataset_dict.DatasetDict): Preprocessed dataset containing train and test parts.\n",
    "    \"\"\"\n",
    "    \n",
    "    # load dataset (only \"train\" part will be enough for this lab).\n",
    "    dataset = load_dataset(dataset_name, split=\"train\")\n",
    "    \n",
    "    # Filter the dialogues of length between input_min_text_length and input_max_text_length characters.\n",
    "    dataset = dataset.filter(lambda x: len(x[\"dialogue\"]) > input_min_text_length and len(x[\"dialogue\"]) <= input_max_text_length, batched=False)\n",
    "\n",
    "    # Prepare tokenizer. Setting device_map=\"auto\" allows to switch between GPU and CPU automatically.\n",
    "    tokenizer = AutoTokenizer.from_pretrained(model_name, device_map=\"auto\")\n",
    "    \n",
    "    def tokenize(sample):\n",
    "        \n",
    "        # Wrap each dialogue with the instruction.\n",
    "        prompt = f\"\"\"\n",
    "Summarize the following conversation.\n",
    "\n",
    "{sample[\"dialogue\"]}\n",
    "\n",
    "Summary:\n",
    "\"\"\"\n",
    "        sample[\"input_ids\"] = tokenizer.encode(prompt)\n",
    "        \n",
    "        # This must be called \"query\", which is a requirement of our PPO library.\n",
    "        sample[\"query\"] = tokenizer.decode(sample[\"input_ids\"])\n",
    "        return sample\n",
    "\n",
    "    # Tokenize each dialogue.\n",
    "    dataset = dataset.map(tokenize, batched=False)\n",
    "    dataset.set_format(type=\"torch\")\n",
    "    \n",
    "    # Split the dataset into train and test parts.\n",
    "    dataset_splits = dataset.train_test_split(test_size=0.2, shuffle=False, seed=42)\n",
    "\n",
    "    return dataset_splits\n",
    "\n",
    "dataset = build_dataset(model_name=model_name,\n",
    "                        dataset_name=huggingface_dataset_name,\n",
    "                        input_min_text_length=200, \n",
    "                        input_max_text_length=1000)\n",
    "\n",
    "print(dataset)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7d03155e-649b-45bb-a5a0-94edd682c069",
   "metadata": {
    "tags": []
   },
   "source": [
    "In the previous lab, you fine-tuned the PEFT model with summarization instructions. The training in the notebook was done on a subset of data. Then you downloaded the checkpoint of the fully trained PEFT model from S3. \n",
    "\n",
    "Let's load the same model checkpoint here:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "e1d44a53-ea1f-4fa5-89e7-d46e37d19935",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "download: s3://dlai-generative-ai/models/peft-dialogue-summary-checkpoint/adapter_config.json to peft-dialogue-summary-checkpoint-from-s3/adapter_config.json\n",
      "download: s3://dlai-generative-ai/models/peft-dialogue-summary-checkpoint/special_tokens_map.json to peft-dialogue-summary-checkpoint-from-s3/special_tokens_map.json\n",
      "download: s3://dlai-generative-ai/models/peft-dialogue-summary-checkpoint/tokenizer_config.json to peft-dialogue-summary-checkpoint-from-s3/tokenizer_config.json\n",
      "download: s3://dlai-generative-ai/models/peft-dialogue-summary-checkpoint/tokenizer.json to peft-dialogue-summary-checkpoint-from-s3/tokenizer.json\n",
      "download: s3://dlai-generative-ai/models/peft-dialogue-summary-checkpoint/adapter_model.bin to peft-dialogue-summary-checkpoint-from-s3/adapter_model.bin\n"
     ]
    }
   ],
   "source": [
    "!aws s3 cp --recursive s3://dlai-generative-ai/models/peft-dialogue-summary-checkpoint/ ./peft-dialogue-summary-checkpoint-from-s3/ "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dec8bea4-addd-4b29-b3af-6db6ea2baeb7",
   "metadata": {
    "tags": []
   },
   "source": [
    "List the model item and check its size (it's less than 15 Mb):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "4288240d-764b-4c49-8df7-b30b9277adbd",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-rw-r--r-- 1 root root 14M May 15 11:18 ./peft-dialogue-summary-checkpoint-from-s3/adapter_model.bin\n"
     ]
    }
   ],
   "source": [
    "!ls -alh ./peft-dialogue-summary-checkpoint-from-s3/adapter_model.bin"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f4226923-67c0-4ea6-8e47-030136b2f191",
   "metadata": {},
   "source": [
    "Prepare a function to pull out the number of model parameters (it is the same as in the previous lab):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "a1f06806-a194-4c14-b64d-e31afd7b658c",
   "metadata": {},
   "outputs": [],
   "source": [
    "def print_number_of_trainable_model_parameters(model):\n",
    "    trainable_model_params = 0\n",
    "    all_model_params = 0\n",
    "    for _, param in model.named_parameters():\n",
    "        all_model_params += param.numel()\n",
    "        if param.requires_grad:\n",
    "            trainable_model_params += param.numel()\n",
    "    return f\"\\ntrainable model parameters: {trainable_model_params}\\nall model parameters: {all_model_params}\\npercentage of trainable model parameters: {100 * trainable_model_params / all_model_params:.2f}%\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "21e06a57-fb80-4f8c-a967-4c7c42a7bfda",
   "metadata": {
    "tags": []
   },
   "source": [
    "Add the adapter to the original FLAN-T5 model. In the previous lab you were adding the fully trained adapter only for inferences, so there was no need to pass LoRA configurations doing that. Now you need to pass them to the constructed PEFT model, also putting `is_trainable=True`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "a1a94b14-b375-45e7-9e49-a7f2c341b4ff",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "4aa25bfd9d624395b6fd2412cfd2dd3e",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading (…)lve/main/config.json:   0%|          | 0.00/1.40k [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "f5e35e914bd6466cbeac28e2446fb148",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading pytorch_model.bin:   0%|          | 0.00/990M [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "1b376d8751cc457ea10eec01f72ae372",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading (…)neration_config.json:   0%|          | 0.00/147 [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "PEFT model parameters to be updated:\n",
      "\n",
      "trainable model parameters: 3538944\n",
      "all model parameters: 251116800\n",
      "percentage of trainable model parameters: 1.41%\n",
      "\n"
     ]
    }
   ],
   "source": [
    "lora_config = LoraConfig(\n",
    "    r=32, # Rank\n",
    "    lora_alpha=32,\n",
    "    target_modules=[\"q\", \"v\"],\n",
    "    lora_dropout=0.05,\n",
    "    bias=\"none\",\n",
    "    task_type=TaskType.SEQ_2_SEQ_LM # FLAN-T5\n",
    ")\n",
    "\n",
    "model = AutoModelForSeq2SeqLM.from_pretrained(model_name, \n",
    "                                              torch_dtype=torch.bfloat16)\n",
    "\n",
    "peft_model = PeftModel.from_pretrained(model, \n",
    "                                       './peft-dialogue-summary-checkpoint-from-s3/', \n",
    "                                       lora_config=lora_config,\n",
    "                                       torch_dtype=torch.bfloat16, \n",
    "                                       device_map=\"auto\",                                       \n",
    "                                       is_trainable=True)\n",
    "\n",
    "print(f'PEFT model parameters to be updated:\\n{print_number_of_trainable_model_parameters(peft_model)}\\n')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a950ae8a-76b9-4951-9c78-9ac7a6349e17",
   "metadata": {},
   "source": [
    "In this lab, you are preparing to fine-tune the LLM using Reinforcement Learning (RL). RL will be briefly discussed in the next section of this lab, but at this stage, you just need to prepare the Proximal Policy Optimization (PPO) model passing the instruct-fine-tuned PEFT model to it. PPO will be used to optimize the RL policy against the reward model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "1e86bab0-6dee-4dff-a754-b584ed962723",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "PPO model parameters to be updated (ValueHead + 769 params):\n",
      "\n",
      "trainable model parameters: 3539713\n",
      "all model parameters: 251117569\n",
      "percentage of trainable model parameters: 1.41%\n",
      "\n",
      "ValueHead(\n",
      "  (dropout): Dropout(p=0.1, inplace=False)\n",
      "  (summary): Linear(in_features=768, out_features=1, bias=True)\n",
      "  (flatten): Flatten(start_dim=1, end_dim=-1)\n",
      ")\n"
     ]
    }
   ],
   "source": [
    "ppo_model = AutoModelForSeq2SeqLMWithValueHead.from_pretrained(peft_model,                                                               \n",
    "                                                               torch_dtype=torch.bfloat16,\n",
    "                                                               is_trainable=True)\n",
    "\n",
    "print(f'PPO model parameters to be updated (ValueHead + 769 params):\\n{print_number_of_trainable_model_parameters(ppo_model)}\\n')\n",
    "print(ppo_model.v_head)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2913ef05-737e-4cdf-9bac-467ee6cf9f76",
   "metadata": {},
   "source": [
    "During PPO, only a few parameters will be updated. Specifically, the parameters of the `ValueHead`. More information about this class of models can be found in the [documentation](https://huggingface.co/docs/trl/main/en/models#trl.create_reference_model). The number of trainable parameters can be computed as $(n+1)*m$, where $n$ is the number of input units (here $n=768$) and $m$ is the number of output units (you have $m=1$). The $+1$ term in the equation takes into account the bias term."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "76c7e2df-0c75-4bd0-bf8d-1f1545ef864e",
   "metadata": {},
   "source": [
    "Now create a frozen copy of the PPO which will not be fine-tuned - a reference model. The reference model will represent the LLM before detoxification. None of the parameters of the reference model will be updated during PPO training. This is on purpose."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "18a9b30a-ad14-4189-8088-d4de447fe247",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Reference model parameters to be updated:\n",
      "\n",
      "trainable model parameters: 0\n",
      "all model parameters: 251117569\n",
      "percentage of trainable model parameters: 0.00%\n",
      "\n"
     ]
    }
   ],
   "source": [
    "ref_model = create_reference_model(ppo_model)\n",
    "\n",
    "print(f'Reference model parameters to be updated:\\n{print_number_of_trainable_model_parameters(ref_model)}\\n')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e3a14848-e83d-4fdd-bc68-eb770c5951d7",
   "metadata": {
    "tags": []
   },
   "source": [
    "Everything is set. It is time to prepare the reward model!"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4bfdf1f7-3509-4adc-812a-2b22bd330137",
   "metadata": {},
   "source": [
    "<a name='2.2'></a>\n",
    "### 2.2 - Prepare Reward Model\n",
    "\n",
    "**Reinforcement Learning (RL)** is one type of machine learning where agents take actions in an environment aimed at maximizing their cumulative rewards. The agent's behavior is defined by the **policy**. And the goal of reinforcement learning is for the agent to learn an optimal, or nearly-optimal, policy that maximizes the **reward function**. \n",
    "\n",
    "In the [previous section](#2.1) the original policy is based on the instruct PEFT model - this is the LLM before detoxification. Then you could ask human labelers to give feedback on the outputs' toxicity. However, it can be expensive to use them for the entire fine-tuning process. A practical way to avoid that is to use a reward model encouraging the agent to detoxify the dialogue summaries. The intuitive approach would be to do some form of sentiment analysis across two classes (`nothate` and `hate`) and give a higher reward if there is higher a chance of getting class `nothate` as an output. \n",
    "\n",
    "For example, we can mention that having human labelers for the entire finetuning process can be expensive. A practical way to avoid that is to use a reward model.\n",
    "\n",
    "use feedback generated by a model\n",
    "\n",
    "You will use [Meta AI's RoBERTa-based hate speech model](https://huggingface.co/facebook/roberta-hate-speech-dynabench-r4-target) for the reward model. This model will output **logits** and then predict probabilities across two classes: `nothate` and `hate`. The logits of the output `nothate` will be taken as a positive reward. Then, the model will be fine-tuned with PPO using those reward values.\n",
    "\n",
    "Create the instance of the required model class for the RoBERTa model. You also need to load a tokenizer to test the model. Notice that the model label `0` will correspond to the class `nothate` and label `1` to the class `hate`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "7f038a9f-e04b-49bc-8923-8ef3816919ee",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "c5d36cb76e924f6fab332a024635d9fb",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading (…)okenizer_config.json:   0%|          | 0.00/1.11k [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "a6f0c10dee754773911298de992ddaa6",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading (…)olve/main/vocab.json:   0%|          | 0.00/899k [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "65b97136838a4cc69b39bf3356749f00",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading (…)olve/main/merges.txt:   0%|          | 0.00/456k [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "897b560579e049c08b9df1e7e2488980",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading (…)cial_tokens_map.json:   0%|          | 0.00/239 [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "637568542cc74279b5c326cd3f050f69",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading (…)lve/main/config.json:   0%|          | 0.00/816 [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "3ad3a6425eeb4de68f29301b27e236a4",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading pytorch_model.bin:   0%|          | 0.00/499M [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "The model weights are not tied. Please use the `tie_weights` method before using the `infer_auto_device` function.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{0: 'nothate', 1: 'hate'}\n"
     ]
    }
   ],
   "source": [
    "toxicity_model_name = \"facebook/roberta-hate-speech-dynabench-r4-target\"\n",
    "toxicity_tokenizer = AutoTokenizer.from_pretrained(toxicity_model_name, device_map=\"auto\")\n",
    "toxicity_model = AutoModelForSequenceClassification.from_pretrained(toxicity_model_name, device_map=\"auto\")\n",
    "print(toxicity_model.config.id2label)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "79d68799-a6e8-42d7-8d61-002e47210c18",
   "metadata": {
    "tags": []
   },
   "source": [
    "Take some non-toxic text, tokenize it, and pass it to the model. Print the output logits, probabilities, and the corresponding reward that will be used for fine-tuning."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "8f4e6a05-2398-4ca7-a176-d5a1ff27fe39",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "logits [not hate, hate]: [3.114100694656372, -2.4896175861358643]\n",
      "probabilities [not hate, hate]: [0.9963293671607971, 0.003670616541057825]\n",
      "reward (high): [3.114100694656372]\n"
     ]
    }
   ],
   "source": [
    "non_toxic_text = \"#Person 1# tells Tommy that he didn't like the movie.\"\n",
    "\n",
    "toxicity_input_ids = toxicity_tokenizer(non_toxic_text, return_tensors=\"pt\").input_ids\n",
    "\n",
    "logits = toxicity_model(input_ids=toxicity_input_ids).logits\n",
    "print(f'logits [not hate, hate]: {logits.tolist()[0]}')\n",
    "\n",
    "# Print the probabilities for [not hate, hate]\n",
    "probabilities = logits.softmax(dim=-1).tolist()[0]\n",
    "print(f'probabilities [not hate, hate]: {probabilities}')\n",
    "\n",
    "# get the logits for \"not hate\" - this is the reward!\n",
    "not_hate_index = 0\n",
    "nothate_reward = (logits[:, not_hate_index]).tolist()\n",
    "print(f'reward (high): {nothate_reward}')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "63f729c5-98c3-4745-96e8-3484670215db",
   "metadata": {},
   "source": [
    "Let's show a toxic comment.  This will have a low reward because it is more toxic."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "0ffc81e4-b220-4f4e-95ec-98ac418612d1",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "logits [not hate, hate]: [-0.6921188831329346, 0.3722729980945587]\n",
      "probabilities [not hate, hate]: [0.25647106766700745, 0.7435289621353149]\n",
      "reward (low): [-0.6921188831329346]\n"
     ]
    }
   ],
   "source": [
    "toxic_text = \"#Person 1# tells Tommy that the movie was terrible, dumb and stupid.\"\n",
    "\n",
    "toxicity_input_ids = toxicity_tokenizer(toxic_text, return_tensors=\"pt\").input_ids\n",
    "\n",
    "logits = toxicity_model(toxicity_input_ids).logits\n",
    "print(f'logits [not hate, hate]: {logits.tolist()[0]}')\n",
    "\n",
    "# Print the probabilities for [not hate, hate]\n",
    "probabilities = logits.softmax(dim=-1).tolist()[0]\n",
    "print(f'probabilities [not hate, hate]: {probabilities}')\n",
    "\n",
    "# Get the logits for \"not hate\" - this is the reward!\n",
    "nothate_reward = (logits[:, not_hate_index]).tolist() \n",
    "print(f'reward (low): {nothate_reward}')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bc6e656e-fefe-4623-8bbb-472a8cf1c3c5",
   "metadata": {},
   "source": [
    "Setup Hugging Face inference pipeline to simplify the code for the toxicity reward model:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "73aab8c6-33eb-4bf4-a816-3866fc3460af",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Reward model output:\n",
      "For non-toxic text\n",
      "[{'label': 'nothate', 'score': 3.114100694656372}, {'label': 'hate', 'score': -2.4896175861358643}]\n",
      "[{'label': 'nothate', 'score': 0.9963293671607971}, {'label': 'hate', 'score': 0.003670616541057825}]\n",
      "For toxic text\n",
      "[{'label': 'hate', 'score': 0.3722729980945587}, {'label': 'nothate', 'score': -0.6921188831329346}]\n",
      "[{'label': 'hate', 'score': 0.7435289621353149}, {'label': 'nothate', 'score': 0.25647106766700745}]\n"
     ]
    }
   ],
   "source": [
    "device = 0 if torch.cuda.is_available() else \"cpu\"\n",
    "\n",
    "sentiment_pipe = pipeline(\"sentiment-analysis\", \n",
    "                          model=toxicity_model_name, \n",
    "                          device=device)\n",
    "reward_logits_kwargs = {\n",
    "    \"top_k\": None, # Return all scores.\n",
    "    \"function_to_apply\": \"none\", # Set to \"none\" to retrieve raw logits.\n",
    "    \"batch_size\": 16\n",
    "}\n",
    "\n",
    "reward_probabilities_kwargs = {\n",
    "    \"top_k\": None, # Return all scores.\n",
    "    \"function_to_apply\": \"softmax\", # Set to \"softmax\" to apply softmax and retrieve probabilities.\n",
    "    \"batch_size\": 16\n",
    "}\n",
    "\n",
    "print(\"Reward model output:\")\n",
    "print(\"For non-toxic text\")\n",
    "print(sentiment_pipe(non_toxic_text, **reward_logits_kwargs))\n",
    "print(sentiment_pipe(non_toxic_text, **reward_probabilities_kwargs))\n",
    "print(\"For toxic text\")\n",
    "print(sentiment_pipe(toxic_text, **reward_logits_kwargs))\n",
    "print(sentiment_pipe(toxic_text, **reward_probabilities_kwargs))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "21302d74-59d8-451f-b287-e86245bf3324",
   "metadata": {},
   "source": [
    "The outputs are the logits for both `nothate` (positive) and `hate` (negative) classes. But PPO will be using logits only of the `nothate` class as the positive reward signal used to help detoxify the LLM outputs."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "36ff3925-70c4-495c-ae26-68e2fc36296b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[{'label': 'nothate', 'score': 3.114100694656372}, {'label': 'hate', 'score': -2.4896175861358643}]\n",
      "[{'label': 'nothate', 'score': 0.9963293671607971}, {'label': 'hate', 'score': 0.003670616541057825}]\n"
     ]
    }
   ],
   "source": [
    "print(sentiment_pipe(non_toxic_text, **reward_logits_kwargs))\n",
    "print(sentiment_pipe(non_toxic_text, **reward_probabilities_kwargs))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "8d11618b-5887-489a-b390-2139e364987f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[{'label': 'hate', 'score': 0.3722729980945587}, {'label': 'nothate', 'score': -0.6921188831329346}]\n",
      "[{'label': 'hate', 'score': 0.7435289621353149}, {'label': 'nothate', 'score': 0.25647106766700745}]\n"
     ]
    }
   ],
   "source": [
    "print(sentiment_pipe(toxic_text, **reward_logits_kwargs))\n",
    "print(sentiment_pipe(toxic_text, **reward_probabilities_kwargs))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "56513033-9bb1-41d5-81e2-54d1249c5c89",
   "metadata": {
    "tags": []
   },
   "source": [
    "<a name='2.3'></a>\n",
    "### 2.3 - Evaluate Toxicity\n",
    "\n",
    "To evaluate the model before and after fine-tuning/detoxification you need to set up the [toxicity evaluation metric](https://huggingface.co/spaces/evaluate-measurement/toxicity). The **toxicity score** is a decimal value between 0 and 1 where 1 is the highest toxicity."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "7de8e99d-60ea-48a2-bdf5-817f80b48979",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "3f63d849a657484f89f9dda0dc446231",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading builder script:   0%|          | 0.00/6.08k [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "toxicity_evaluator = evaluate.load(\"toxicity\", \n",
    "                                    toxicity_model_name,\n",
    "                                    module_type=\"measurement\",\n",
    "                                    toxic_label=\"hate\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "840fbc47-c5c2-469a-b5f2-6407e8f0bfde",
   "metadata": {
    "tags": []
   },
   "source": [
    "Try to calculate toxicity for the same sentences as in section [2.2](#2.2). It's no surprise that the toxicity scores are the probabilities of `hate` class returned directly from the reward model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "5298f91c-30d1-4d17-95a7-553952ac97b5",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Toxicity score for non-toxic text:\n",
      "[0.003670616541057825]\n",
      "\n",
      "Toxicity score for toxic text:\n",
      "[0.7435289621353149]\n"
     ]
    }
   ],
   "source": [
    "toxicity_score = toxicity_evaluator.compute(predictions=[\n",
    "    non_toxic_text\n",
    "])\n",
    "\n",
    "print(\"Toxicity score for non-toxic text:\")\n",
    "print(toxicity_score[\"toxicity\"])\n",
    "\n",
    "toxicity_score = toxicity_evaluator.compute(predictions=[\n",
    "    toxic_text\n",
    "])\n",
    "\n",
    "print(\"\\nToxicity score for toxic text:\")\n",
    "print(toxicity_score[\"toxicity\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7d3e835b-14b9-4646-b1c9-c975ef3ea944",
   "metadata": {
    "tags": []
   },
   "source": [
    "This evaluator can be used to compute the toxicity of the dialogues prepared in section [2.1](#2.1). You will need to pass the test dataset (`dataset[\"test\"]`), the same tokenizer which was used in that section, the frozen PEFT model prepared in section [2.2](#2.2), and the toxicity evaluator. It is convenient to wrap the required steps in the function `evaluate_toxicity`. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "316ab128-33ff-4a1e-8936-47bfa29d48a3",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "def evaluate_toxicity(model, \n",
    "                      toxicity_evaluator, \n",
    "                      tokenizer, \n",
    "                      dataset, \n",
    "                      num_samples):\n",
    "    \n",
    "    \"\"\"\n",
    "    Preprocess the dataset and split it into train and test parts.\n",
    "\n",
    "    Parameters:\n",
    "    - model (trl model): Model to be evaluated.\n",
    "    - toxicity_evaluator (evaluate_modules toxicity metrics): Toxicity evaluator.\n",
    "    - tokenizer (transformers tokenizer): Tokenizer to be used.\n",
    "    - dataset (dataset): Input dataset for the evaluation.\n",
    "    - num_samples (int): Maximum number of samples for the evaluation.\n",
    "        \n",
    "    Returns:\n",
    "    tuple: A tuple containing two numpy.float64 values:\n",
    "    - mean (numpy.float64): Mean of the samples toxicity.\n",
    "    - std (numpy.float64): Standard deviation of the samples toxicity.\n",
    "    \"\"\"\n",
    "\n",
    "    max_new_tokens=100\n",
    "\n",
    "    toxicities = []\n",
    "    input_texts = []\n",
    "    for i, sample in tqdm(enumerate(dataset)):\n",
    "        input_text = sample[\"query\"]\n",
    "\n",
    "        if i > num_samples:\n",
    "            break\n",
    "            \n",
    "        input_ids = tokenizer(input_text, return_tensors=\"pt\", padding=True).input_ids\n",
    "        \n",
    "        generation_config = GenerationConfig(max_new_tokens=max_new_tokens,\n",
    "                                             tok_k=0.0,\n",
    "                                             top_p=1.0,\n",
    "                                             do_sample=True)\n",
    "\n",
    "        response_token_ids = model.generate(input_ids=input_ids,\n",
    "                                            generation_config=generation_config)\n",
    "        \n",
    "        generated_text = tokenizer.decode(response_token_ids[0], skip_special_tokens=True)\n",
    "        \n",
    "        toxicity_score = toxicity_evaluator.compute(predictions=[(input_text + \" \" + generated_text)])\n",
    "\n",
    "        toxicities.extend(toxicity_score[\"toxicity\"])\n",
    "\n",
    "    # Compute mean & std using np.\n",
    "    mean = np.mean(toxicities)\n",
    "    std = np.std(toxicities)\n",
    "        \n",
    "    return mean, std"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aed269c3-dbd7-4d45-bc44-c6ab6d4ae141",
   "metadata": {
    "tags": []
   },
   "source": [
    "And now perform the calculation of the model toxicity before fine-tuning/detoxification:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "c11ede15-dc1a-4a7e-a60d-b9cadfc7d876",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "11it [00:24,  2.25s/it]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "toxicity [mean, std] before detox: [0.027250663118055938, 0.03593675945422879]\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "tokenizer = AutoTokenizer.from_pretrained(model_name, device_map=\"auto\")\n",
    "\n",
    "mean_before_detoxification, std_before_detoxification = evaluate_toxicity(model=ref_model, \n",
    "                                                                          toxicity_evaluator=toxicity_evaluator, \n",
    "                                                                          tokenizer=tokenizer, \n",
    "                                                                          dataset=dataset[\"test\"], \n",
    "                                                                          num_samples=10)\n",
    "\n",
    "print(f'toxicity [mean, std] before detox: [{mean_before_detoxification}, {std_before_detoxification}]')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1ba81c90-1ac8-4403-ac1a-d4c75c6df4f0",
   "metadata": {},
   "source": [
    "<a name='3'></a>\n",
    "## 3 - Perform Fine-Tuning to Detoxify the Summaries\n",
    "Optimize a RL policy against the reward model using Proximal Policy Optimization (PPO)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5516e318-8fce-4ca7-bf19-b7baf5255480",
   "metadata": {},
   "source": [
    "<a name='3.1'></a>\n",
    "### 3.1 - Initialize `PPOTrainer`\n",
    " \n",
    "For the `PPOTrainer` initialization, you will need a collator. Here it will be a function transforming the dictionaries in a particular way. You can define and test it:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "8b7be1c0-382a-4fe2-8174-470f3e333e84",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collator input: [{'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}]\n",
      "Collator output: {'key1': ['value1'], 'key2': ['value2'], 'key3': ['value3']}\n"
     ]
    }
   ],
   "source": [
    "def collator(data):\n",
    "    return dict((key, [d[key] for d in data]) for key in data[0])\n",
    "\n",
    "test_data = [{\"key1\": \"value1\", \"key2\": \"value2\", \"key3\": \"value3\"}]\n",
    "print(f'Collator input: {test_data}')\n",
    "print(f'Collator output: {collator(test_data)}')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "080c2e92-4988-4944-8353-0e1bb2048072",
   "metadata": {},
   "source": [
    "Set up the configuration parameters. Load the `ppo_model` and the tokenizer. You will also load a frozen version of the model `ref_model`. The first model is optimized while the second model serves as a reference to calculate the KL-divergence from the starting point. This works as an additional reward signal in the PPO training to make sure the optimized model does not deviate too much from the original LLM."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "494e09a1-9024-4f38-91eb-d73cdc3239e6",
   "metadata": {},
   "outputs": [],
   "source": [
    "learning_rate=1.41e-5\n",
    "max_ppo_epochs=1\n",
    "mini_batch_size=4\n",
    "batch_size=16\n",
    "\n",
    "config = PPOConfig(\n",
    "    model_name=model_name,    \n",
    "    learning_rate=learning_rate,\n",
    "    ppo_epochs=max_ppo_epochs,\n",
    "    mini_batch_size=mini_batch_size,\n",
    "    batch_size=batch_size\n",
    ")\n",
    "\n",
    "ppo_trainer = PPOTrainer(config=config, \n",
    "                         model=ppo_model, \n",
    "                         ref_model=ref_model, \n",
    "                         tokenizer=tokenizer, \n",
    "                         dataset=dataset[\"train\"], \n",
    "                         data_collator=collator)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7ad77d2c-3800-4e15-bb38-3851d94ad374",
   "metadata": {},
   "source": [
    "<a name='3.2'></a>\n",
    "### 3.2 - Fine-Tune the Model"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0cac21fb-fea5-4e80-a741-87f35ae72c62",
   "metadata": {},
   "source": [
    "The fine-tuning loop consists of the following main steps:\n",
    "1. Get the query responses from the policy LLM (PEFT model).\n",
    "2. Get sentiments for query/responses from hate speech RoBERTa model.\n",
    "3. Optimize policy with PPO using the (query, response, reward) triplet.\n",
    "\n",
    "The operation is running if you see the following metrics appearing:\n",
    "* `objective/kl`: minimize kl divergence,\n",
    "* `ppo/returns/mean`: maximize mean returns,\n",
    "* `ppo/policy/advantages_mean`: maximize advantages."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "01536b7e-2f0f-4986-a97c-6ecfabf518d4",
   "metadata": {
    "tags": []
   },
   "source": [
    "<img src=\"\" alt=\"Time alert open medium\"/>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "4bc55397-92b8-4f61-9ec2-c8b39d5f8962",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "0it [00:00, ?it/s]You're using a T5TokenizerFast tokenizer. Please note that with a fast tokenizer, using the `__call__` method is faster than using a method to encode the text followed by a call to the `pad` method to get a padded encoding.\n",
      "1it [01:44, 104.94s/it]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "objective/kl: 29.314075469970703\n",
      "ppo/returns/mean: -0.4292612075805664\n",
      "ppo/policy/advantages_mean: 6.132159224847555e-10\n",
      "---------------------------------------------------------------------------------------------------\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2it [03:25, 102.35s/it]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "objective/kl: 33.92654037475586\n",
      "ppo/returns/mean: -0.5876554250717163\n",
      "ppo/policy/advantages_mean: -5.736052077764953e-09\n",
      "---------------------------------------------------------------------------------------------------\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "3it [04:58, 98.29s/it] "
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "objective/kl: 26.41731071472168\n",
      "ppo/returns/mean: -0.34014931321144104\n",
      "ppo/policy/advantages_mean: 1.14067217893421e-08\n",
      "---------------------------------------------------------------------------------------------------\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "4it [06:22, 92.32s/it]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "objective/kl: 21.340606689453125\n",
      "ppo/returns/mean: -0.14187607169151306\n",
      "ppo/policy/advantages_mean: -1.5046509815874742e-08\n",
      "---------------------------------------------------------------------------------------------------\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "5it [07:51, 91.15s/it]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "objective/kl: 21.950702667236328\n",
      "ppo/returns/mean: 0.11500176042318344\n",
      "ppo/policy/advantages_mean: -3.3763356555027713e-09\n",
      "---------------------------------------------------------------------------------------------------\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "6it [09:33, 95.09s/it]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "objective/kl: 30.00735855102539\n",
      "ppo/returns/mean: -0.37458187341690063\n",
      "ppo/policy/advantages_mean: 1.5465744240827917e-08\n",
      "---------------------------------------------------------------------------------------------------\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "7it [11:03, 93.42s/it]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "objective/kl: 27.254785537719727\n",
      "ppo/returns/mean: -0.3798617422580719\n",
      "ppo/policy/advantages_mean: -1.3937912157757637e-08\n",
      "---------------------------------------------------------------------------------------------------\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "8it [12:31, 91.68s/it]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "objective/kl: 29.540206909179688\n",
      "ppo/returns/mean: -0.5173881649971008\n",
      "ppo/policy/advantages_mean: 4.040108692038302e-09\n",
      "---------------------------------------------------------------------------------------------------\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "9it [14:09, 93.63s/it]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "objective/kl: 27.104557037353516\n",
      "ppo/returns/mean: -0.41745492815971375\n",
      "ppo/policy/advantages_mean: 8.328595590967325e-09\n",
      "---------------------------------------------------------------------------------------------------\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "10it [15:44, 94.40s/it]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "objective/kl: 26.833106994628906\n",
      "ppo/returns/mean: -0.3821057379245758\n",
      "ppo/policy/advantages_mean: -1.8973297599700345e-08\n",
      "---------------------------------------------------------------------------------------------------\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "output_min_length = 100\n",
    "output_max_length = 400\n",
    "output_length_sampler = LengthSampler(output_min_length, output_max_length)\n",
    "\n",
    "generation_kwargs = {\n",
    "    \"min_length\": 5,\n",
    "    \"top_k\": 0.0,\n",
    "    \"top_p\": 1.0,\n",
    "    \"do_sample\": True\n",
    "}\n",
    "\n",
    "reward_kwargs = {\n",
    "    \"top_k\": None, # Return all scores.\n",
    "    \"function_to_apply\": \"none\", # You want the raw logits without softmax.\n",
    "    \"batch_size\": 16\n",
    "}\n",
    "\n",
    "max_ppo_steps = 10\n",
    "\n",
    "for step, batch in tqdm(enumerate(ppo_trainer.dataloader)):\n",
    "    # Break when you reach max_steps.\n",
    "    if step >= max_ppo_steps:\n",
    "        break   \n",
    "\n",
    "    prompt_tensors = batch[\"input_ids\"]\n",
    "\n",
    "    # Get response from FLAN-T5/PEFT LLM.\n",
    "    summary_tensors = []\n",
    "\n",
    "    for prompt_tensor in prompt_tensors:\n",
    "        max_new_tokens = output_length_sampler()        \n",
    "            \n",
    "        generation_kwargs[\"max_new_tokens\"] = max_new_tokens\n",
    "        summary = ppo_trainer.generate(prompt_tensor, **generation_kwargs)\n",
    "        \n",
    "        summary_tensors.append(summary.squeeze()[-max_new_tokens:])\n",
    "        \n",
    "    # This needs to be called \"response\".\n",
    "    batch[\"response\"] = [tokenizer.decode(r.squeeze()) for r in summary_tensors]\n",
    "\n",
    "    # Compute reward outputs.\n",
    "    query_response_pairs = [q + r for q, r in zip(batch[\"query\"], batch[\"response\"])]    \n",
    "    rewards = sentiment_pipe(query_response_pairs, **reward_kwargs)\n",
    "\n",
    "    # You use the `nothate` item because this is the score for the positive `nothate` class.\n",
    "    reward_tensors = [torch.tensor(reward[not_hate_index][\"score\"]) for reward in rewards]    \n",
    "\n",
    "    # Run PPO step.\n",
    "    stats = ppo_trainer.step(prompt_tensors, summary_tensors, reward_tensors)\n",
    "    ppo_trainer.log_stats(stats, batch, reward_tensors)\n",
    "    \n",
    "    print(f'objective/kl: {stats[\"objective/kl\"]}')\n",
    "    print(f'ppo/returns/mean: {stats[\"ppo/returns/mean\"]}')\n",
    "    print(f'ppo/policy/advantages_mean: {stats[\"ppo/policy/advantages_mean\"]}')\n",
    "    print('-'.join('' for x in range(100)))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5b648cb7-89e2-40b8-9507-9c07bdfd9ebf",
   "metadata": {},
   "source": [
    "<img src=\"\" alt=\"Time alert close\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7903f5df-a9de-41eb-b239-38bc367b5654",
   "metadata": {},
   "source": [
    "<a name='3.3'></a>\n",
    "### 3.3 - Evaluate the Model Quantitatively\n",
    "\n",
    "Load the PPO/PEFT model back in from disk and use the test dataset split to evaluate the toxicity score of the RL-fine-tuned model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "3b093d43-6197-4cc0-b933-29030479a7d0",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "11it [00:20,  1.89s/it]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "toxicity [mean, std] after detox: [0.016664074215275996, 0.017401415483226337]\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "mean_after_detoxification, std_after_detoxification = evaluate_toxicity(model=ppo_model, \n",
    "                                                                        toxicity_evaluator=toxicity_evaluator, \n",
    "                                                                        tokenizer=tokenizer, \n",
    "                                                                        dataset=dataset[\"test\"], \n",
    "                                                                        num_samples=10)\n",
    "print(f'toxicity [mean, std] after detox: [{mean_after_detoxification}, {std_after_detoxification}]')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f42895cc-7bbf-45e1-a7c7-78ee29cd8009",
   "metadata": {
    "tags": []
   },
   "source": [
    "And compare the toxicity scores of the reference model (before detoxification) and fine-tuned model (after detoxification)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "77cc3af2-6600-4673-874b-917c05247ae3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Percentage improvement of toxicity score after detoxification:\n",
      "mean: 38.85%\n",
      "std: 51.58%\n"
     ]
    }
   ],
   "source": [
    "mean_improvement = (mean_before_detoxification - mean_after_detoxification) / mean_before_detoxification\n",
    "std_improvement = (std_before_detoxification - std_after_detoxification) / std_before_detoxification\n",
    "\n",
    "print(f'Percentage improvement of toxicity score after detoxification:')\n",
    "print(f'mean: {mean_improvement*100:.2f}%')\n",
    "print(f'std: {std_improvement*100:.2f}%')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "66030581-b6f7-41d7-a7e6-2466226833be",
   "metadata": {},
   "source": [
    "<a name='3.4'></a>\n",
    "### 3.4 - Evaluate the Model Qualitatively\n",
    "\n",
    "Let's inspect some examples from the test dataset. You can compare the original `ref_model` to the fine-tuned/detoxified `ppo_model` using the toxicity evaluator."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "12fdc491-5437-41dd-980b-0d04304292dd",
   "metadata": {},
   "source": [
    "<img src=\"\" alt=\"Time alert open medium\"/>\n",
    "​"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "22cc8313-20ae-4d32-855e-9b2866fa3085",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 20/20 [01:26<00:00,  4.32s/it]\n"
     ]
    }
   ],
   "source": [
    "batch_size = 20\n",
    "compare_results = {}\n",
    "\n",
    "df_batch = dataset[\"test\"][0:batch_size]\n",
    "\n",
    "compare_results[\"query\"] = df_batch[\"query\"]\n",
    "prompt_tensors = df_batch[\"input_ids\"]\n",
    "\n",
    "summary_tensors_ref = []\n",
    "summary_tensors = []\n",
    "\n",
    "# Get response from ppo and base model.\n",
    "for i in tqdm(range(batch_size)):\n",
    "    gen_len = output_length_sampler()\n",
    "    generation_kwargs[\"max_new_tokens\"] = gen_len\n",
    "    \n",
    "    summary = ref_model.generate(\n",
    "        input_ids=torch.as_tensor(prompt_tensors[i]).unsqueeze(dim=0).to(device), \n",
    "        **generation_kwargs\n",
    "    ).squeeze()[-gen_len:]\n",
    "    summary_tensors_ref.append(summary)\n",
    "\n",
    "    summary = ppo_model.generate(\n",
    "        input_ids=torch.as_tensor(prompt_tensors[i]).unsqueeze(dim=0).to(device), \n",
    "        **generation_kwargs\n",
    "    ).squeeze()[-gen_len:]\n",
    "    summary_tensors.append(summary)\n",
    "\n",
    "# Decode responses.\n",
    "compare_results[\"response_before\"] = [tokenizer.decode(summary_tensors_ref[i]) for i in range(batch_size)]\n",
    "compare_results[\"response_after\"] = [tokenizer.decode(summary_tensors[i]) for i in range(batch_size)]\n",
    "\n",
    "# Sentiment analysis of query/response pairs before/after.\n",
    "texts_before = [d + s for d, s in zip(compare_results[\"query\"], compare_results[\"response_before\"])]\n",
    "rewards_before = sentiment_pipe(texts_before, **reward_kwargs)\n",
    "compare_results[\"reward_before\"] = [reward[not_hate_index][\"score\"] for reward in rewards_before]\n",
    "\n",
    "texts_after = [d + s for d, s in zip(compare_results[\"query\"], compare_results[\"response_after\"])]\n",
    "rewards_after = sentiment_pipe(texts_after, **reward_kwargs)\n",
    "compare_results[\"reward_after\"] = [reward[not_hate_index][\"score\"] for reward in rewards_after]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "13a3853f-be22-4a95-95d8-a4b61eb2468f",
   "metadata": {
    "tags": []
   },
   "source": [
    "<img src=\"\" alt=\"Time alert close\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "65b70892-4c22-4bed-9d1e-9da3f4f0c97f",
   "metadata": {
    "tags": []
   },
   "source": [
    "Store and review the results in a DataFrame"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "e06fff0f-9dba-4517-9424-a5ebd81e8f49",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>query</th>\n",
       "      <th>response_before</th>\n",
       "      <th>response_after</th>\n",
       "      <th>reward_before</th>\n",
       "      <th>reward_after</th>\n",
       "      <th>reward_diff</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Summarize the following conversation. #Person1#: Oh, my God! What's this? #Person2#: What? #Person1#: Look! This window is open. #Person2#: Did you open it before we left? #Person1#: Are you kidding? It's winter. Why would I open it? #Person2#: I don't know. Wait. Is this yours? #Person1#: No! Oh, my God! Someone has broken into the house. #Person2#: It looks that way. That's probably why the door wasn't locked when we came in. #Person1#: I locked it when I left though. #Person2#: Yes, but t...</td>\n",
       "      <td>&lt;pad&gt; Allen has broken into the house and one of his things was stolen. Allen's mind stops and recognizes the only thing the robber stole. Allen will go to the windows.&lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; Allen and #Person1# are concerned about what a robber stole, though they don't think there will be one alive. Allen had a picture of the bird but the bird locked it and made the bird flee, which he found through the door then not locked at all.&lt;/s&gt;</td>\n",
       "      <td>1.577376</td>\n",
       "      <td>2.092901</td>\n",
       "      <td>0.515524</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Summarize the following conversation. #Person1#: Judy, what is everybody talking about? #Person2#: Haven't you heard? Richard was fired by our manager. #Person1#: You're kidding. It can't be true. #Person2#: Believe it or not. Everybody is talking about it in the company. #Person1#: Really? I'm surprised. #Person2#: Me too. Summary: &lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; Judy and her boss are surprised that Richard was fired. So, Judy and #Person2# think it's true.&lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; Judy and Judy understand Richard was fired. Judy is surprised because everybody is talking about it in the company.&lt;/s&gt;</td>\n",
       "      <td>0.998530</td>\n",
       "      <td>1.466953</td>\n",
       "      <td>0.468423</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Summarize the following conversation. #Person1#: Mom, I just finished my paper. Can you proofread it before I hand it in? #Person2#: Sure, let's take a look. Sweetie, this is terrific. Your ideas are so original. #Person1#: Thanks. #Person2#: I can tell you worked hard on it. #Person1#: I really did! I started thinking about what I wanted to say three weeks ago. #Person2#: Well, it was definitely worth all the time. #Person1#: Let's just hope my teacher agrees. Summary: &lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; #Person1# asks #Person2# about mom's imprint essay. #Person1# got excellent ideas from #Person1#'s mom. #Person2# thinks it was worth all the time.&lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; Mother lends her a paper proofread before handing it in. It has been a hard one, but Mom shows sarcastic displeasure.&lt;/s&gt;</td>\n",
       "      <td>2.231749</td>\n",
       "      <td>2.643997</td>\n",
       "      <td>0.412248</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Summarize the following conversation. #Person1#: Could you help me, Sir? My flight got in 15 minutes ago. Everyone else has picked up the luggage but mine hasn't come through. #Person2#: I'm sorry, Madam, I'll go and find out if there is any more to come. Summary: &lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; #Person1# doesn't know her flight is running and she cannot get someone to help her.&lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; #Person1# says everyone else has picked up the luggage but their flight got into 15 minutes ago.&lt;/s&gt;</td>\n",
       "      <td>1.835569</td>\n",
       "      <td>2.229936</td>\n",
       "      <td>0.394368</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Summarize the following conversation. #Person1#: Today more and more families have personal computers. People have wider range of choice to communicate with the outside world. #Person2#: Right. With the establishment of Internet and a lot of web companies, people are getting more and more dependent on the web. #Person1#: One of the common uses of PC is that people can buy goods through it without going out to the physical stores. #Person2#: Can you tell me how it is done? #Person1#: If a cus...</td>\n",
       "      <td>&lt;pad&gt; #Person1# tells #Person2# how the entire people have personal computers. After a successful test of units by a customer, #Person2# can buy goods through the computer without going to the physical stores. #Person2# tells #Person1# in detail how the computer can be used to buy goods.&lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; #Person1# shows some examples of the uses of a PC. Takes a lesson from PC for people to buy some groceries by relying on the web and connects to the sales company. She tells #Person2# how she can place an order online and enjoys the service because the deliver is free.&lt;/s&gt;</td>\n",
       "      <td>2.635307</td>\n",
       "      <td>2.945903</td>\n",
       "      <td>0.310597</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>Summarize the following conversation. #Person1#: Here is the final draft of our contract. I'm glad that we have reached an agreement on almost every term in our trade. #Person2#: Yes, it seems to me we have come quite a long way. However, let me take a close look at the final draft. #Person1#: Do you have some points to bring up? #Person2#: Well, everything we've discussed seems to be here. #Person1#: Yes, including a description of the shirts you want to purchase this time, the total amount...</td>\n",
       "      <td>&lt;pad&gt; #Person2# tells #Person1# that they still have a good agreement on almost every term in their trade. #Person1# shows #Person2# the final draft with photos of every detail. #Person2# will sign the contract now.&lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; #Person2# has briefed #Person1# about outstanding terms and approaches the final draft. They have brought up points in the final draft. They have several days to finish their notes on the terms and defects; therefore they want to sign the contract now.&lt;/s&gt;</td>\n",
       "      <td>3.081573</td>\n",
       "      <td>3.372005</td>\n",
       "      <td>0.290432</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>Summarize the following conversation. #Person1#: I would like to order some internet today. #Person2#: What kind would you like? #Person1#: What kind of internet is there? #Person2#: You can get DEL or dial-up. #Person1#: Which of those two is best? #Person2#: I would recommend DEL. #Person1#: So that one better? #Person2#: It's better because it doesn't tie up the phone. #Person1#: What do you mean by that? #Person2#: DEL isn't connected through your phone line, but dial-up is. #Person1#: S...</td>\n",
       "      <td>&lt;pad&gt; #Person1# is buying DEL and converts #Person1#'s football to a DEL relay or dial-up internet. #Person2# thinks DEL is not connected through a phone line, but dial-up is.&lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; #Person2# the best Internet is DEL. It means it isn't connected beyond the phone line. Since DEL isn't connected through the phone line, it's still possible to use a phone when using DEL.&lt;/s&gt;</td>\n",
       "      <td>2.184070</td>\n",
       "      <td>2.379267</td>\n",
       "      <td>0.195198</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>Summarize the following conversation. #Person1#: Excuse me, could you tell me how to get to the Cross Bakery building? #Person2#: The Cross Bakery building? Oh sure. You're actually walking in the opposite direction. #Person1#: Oh, you're kidding! I thought I was heading east. #Person2#: No, east is the other direction. To get to the Bakery, you need to turn around and go three blocks to Broadway. When you get to the intersection of Broadway and Elm, you hang a left. Go straight down that st...</td>\n",
       "      <td>&lt;pad&gt; #Person1# wants to do directions to the Cross Bakery yet #Person2# tells her the opposite direction to get there. #Person1# begins at Broadway and meets the Cross Bakery building. #Person2# will show #Person1# a way&lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; #Person1# asks for #Person2#'s directions and asks for the direction on which to get to the Bakery. #Person2# offers #Person1# an extended trip by subway.&lt;/s&gt;</td>\n",
       "      <td>2.654602</td>\n",
       "      <td>2.839283</td>\n",
       "      <td>0.184682</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>Summarize the following conversation. #Person1#: How much are you asking for this? #Person2#: I'm offering them to you at 150 yuan a piece. Is that all right? #Person1#: Is tax already included in their price? #Person2#: Yes. Our price can't be matched. #Person1#: Would you consider a volume discount? #Person2#: If you buy 1, 000 or more, you'll get a 10 % discount. #Person1#: I'll accept your offer. Summary: &lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; #Person1# offers to buy a cheap car new. #Person2# offers a discount if #Person1# buys more than 1,000 items.&lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; #Person1# buys a bird for 150 yuan per piece and will get 10% discount if purchase more than 1 000 of a piece.&lt;/s&gt;</td>\n",
       "      <td>2.325330</td>\n",
       "      <td>2.508447</td>\n",
       "      <td>0.183116</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>Summarize the following conversation. #Person1#: What can I do for you, madam? #Person2#: I'd like to buy a toy car for my son. #Person1#: How about this one? #Person2#: It looks nice. How much is it? #Person1#: They're three hundred dollars. #Person2#: Oh, I'm afraid it's too expensive. Can you show me something cheaper? #Person1#: OK, This one is one hundred and twenty. It's the cheapest here. #Person2#: OK, I'll take it. Here's the money. #Person1#: Thank you very much. Summary: &lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; #Person2# wants to buy a toy car for her son. They lose it because it's too expensive. #Person1# helps to find it for her and helps #Person2# pay the price.&lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; #Person1# wants to sell a toy car for her son. #Person1# recommends one hundred and twenty dollars and offers it to #Person2#.&lt;/s&gt;</td>\n",
       "      <td>1.195809</td>\n",
       "      <td>1.301500</td>\n",
       "      <td>0.105691</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>Summarize the following conversation. #Person1#: Could you help me figure out how to look for a job? #Person2#: We have lots of options, what type of job do you need? #Person1#: I want to work in an office. #Person2#: Do you want to work part-time or full-time? #Person1#: I want to work full-time. #Person2#: We have binders with local job listings or you can make use of the computers. OK? #Person1#: I am confused a bit but I am sure that I can figure it out. #Person2#: If you make an appoint...</td>\n",
       "      <td>&lt;pad&gt; #Person1# asks #Person2# to help look for a job. #Person2# recommends #Person1# to see a job counselor, but #Person1# doesn't think #Person1# need to do that.&lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; #Person1# asks #Person2# about using the job center and how to find a job. #Person2# helped #Person1# with shoplifting in the same location and timely within the company.&lt;/s&gt;</td>\n",
       "      <td>2.113558</td>\n",
       "      <td>2.147066</td>\n",
       "      <td>0.033508</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>Summarize the following conversation. #Person1#: Let's take a coffee break, shall we? #Person2#: I wish I could, but I can't. #Person1#: What keeps you so busy? You've been sitting there for hours. You've got to walk around. You just can't stay on the computer forever. #Person2#: Well, I am up to my neck in work. I've got to finish this report. Sarah needs it by noon. I don't want to be scolded if I can't finish my work by the deadline. #Person1#: I understand that, but you'd feel better if ...</td>\n",
       "      <td>&lt;pad&gt; #Person1# invites #Person2# to have a coffee break enjoying the fast pace of work, unlike #Person2# who is still too busy to do much work afterwards.&lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; #Person1# wants to take a coffee, but #Person2# can't take a break because he's up to his neck in work. #Person1# explained that #Person2# would feel better if they took a break.&lt;/s&gt;</td>\n",
       "      <td>1.959802</td>\n",
       "      <td>1.826756</td>\n",
       "      <td>-0.133046</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>Summarize the following conversation. #Person1#: Amanda, how do you like this peaked cap? #Person2#: Didn't you say you want to buy a top hat? #Person1#: But I think this one fits me Well. Why don't you try on the sombrero in black? #Person2#: I don't like caps at all. Summary: &lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; Amanda likes going for top hats but #Person2# doesn't want to buy caps.&lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; Amanda doesn't like a cap but she likes this one because it fits her well.&lt;/s&gt;</td>\n",
       "      <td>1.396727</td>\n",
       "      <td>1.256419</td>\n",
       "      <td>-0.140307</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>Summarize the following conversation. #Person1#: Where shall I register, please? #Person2#: Here. Do you have a registration card? #Person1#: Yes. Here you are. #Person2#: Please register your information here and pay for it. And I'll make a medical record for you. #Person1#: OK. How much do I need to pay for the registration? #Person2#: Please pay ten yuan for the registration. #Person1#: Here is my money. #Person2#: This is your registration card. Please don't lose it and bring it whenever...</td>\n",
       "      <td>&lt;pad&gt; #Person2# invites #Person1# to a clinic. #Person1# tells #Person2# the visiting hours is 11:00 GMT and #Person1# pays for the registration.&lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; #Person2# registers his information for the surgery for #Person1#. #Person2# wants to make a medical record and describes the terms of treatment. #Person1# will go down this way and see the doctor.&lt;/s&gt;</td>\n",
       "      <td>1.620430</td>\n",
       "      <td>1.424039</td>\n",
       "      <td>-0.196391</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>Summarize the following conversation. #Person1#: I'd like to have this cashed, please. #Person2#: Please put you name and address here. May I see your passport? #Person1#: Yes. #Person2#: How would you like it? #Person1#: Ten hundreds and ten twenties, and the rest in small change, please. #Person2#: OK. Here you are. Summary: &lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; The cash for #Person1# was cashed with $10s and twenties in small change. #Person1# is satisfied with the cash and chooses to change it.&lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; #Person2# is shopping for cash and helps #Person1# to get ten hundreds and ten twenties bills.&lt;/s&gt;</td>\n",
       "      <td>1.972783</td>\n",
       "      <td>1.769356</td>\n",
       "      <td>-0.203427</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>Summarize the following conversation. #Person1#: So how did you like the restaurant? #Person2#: Actually, it could have been better. #Person1#: What didn't you like about it? #Person2#: It is a new restaurant. I don't think they have their act together yet. #Person1#: What did you think about the food? #Person2#: I felt that the food was pretty mediocre. #Person1#: The service wasn't that great, either. #Person2#: I agree. The service was not good. #Person1#: Do you think that you want to tr...</td>\n",
       "      <td>&lt;pad&gt; #Person1# asks #Person2# how the restaurant was and calls in a rating.&lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; #Person2# loved the restaurant but it's a new one and service wasn't very good. #Person2# was angry with the restaurant because it's new and it's not good.&lt;/s&gt;</td>\n",
       "      <td>2.401509</td>\n",
       "      <td>2.186926</td>\n",
       "      <td>-0.214583</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>Summarize the following conversation. #Person1#: Hello. I want to reconfirm our flight to London. #Person2#: Yes, sir. Did you call the airline? #Person1#: Yes, I did. But I couldn't communicate with them in English. They speak only Spanish. So I need your help. #Person2#: Certainly, sir. What is the flight number and when are you leaving? #Person1#: We are taking IB 385 to London tomorrow at 1 p. m. #Person2#: Oh, I see, sir. We have the airline office inside the hotel. They have an English...</td>\n",
       "      <td>&lt;pad&gt; #Person1# wants to confirm their flight for tomorrow at 1 p.m. #Person2# calls '35' so #Person1# can call the airline office to confirm the data. #Person1# has just dialed 135.&lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; The airline can't tell #Person1# how to get the flight to London from #Person2#'s office.&lt;/s&gt;</td>\n",
       "      <td>1.978626</td>\n",
       "      <td>1.759486</td>\n",
       "      <td>-0.219140</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>Summarize the following conversation. #Person1#: I'm forming a music band. #Person2#: Do you already know how to play an instrument? #Person1#: Uh... Yeah! I'Ve told you a thousand times that I'm learning to play the drums. Now that I know how to play well, I would like to form a rock band. #Person2#: Aside from yourself, who are the other members of the band? #Person1#: We have a guy who plays guitar, and another who plays bass. Although we still haven't found anyone to be our singer. You t...</td>\n",
       "      <td>&lt;pad&gt; #Person1# wants to form a rock band after learning to play the drums. #Person2# invites #Person1# to audition at #Person1#'s house this weekend, because #Person1# doesn't have enough space for the amplifiers, microphones, and even the drums. #Person1#'s music talent is enough so #Person2# can audition this weekend.&lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; #Person1# wants to start a music band and wants to do so when he realizes there's no singer. #Person1# decides to audition but the audition is at #Person1#'s home.&lt;/s&gt;</td>\n",
       "      <td>2.767497</td>\n",
       "      <td>2.376706</td>\n",
       "      <td>-0.390790</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>Summarize the following conversation. #Person1#: Hello? #Person2#: Hello? #Person1#: Can I speak to Li Hong, please? #Person2#: Speaking. #Person1#: Hi, Li Hong. This is Alice. #Person2#: Hi, Alice. How are you? #Person1#: Not bad. Li Hong, I am sorry that I can't go to see Mrs. Brown with you tomorrow morning. My mother is ill. I must take care of her. #Person2#: I'm sorry to hear that. You'd better stay at home. After all, we can visit Mrs. Brown later #Person1#: OK. Bye - bye. #Person2#: ...</td>\n",
       "      <td>&lt;pad&gt; Alice can't visit Mrs. Brown tomorrow morning, because her mother is ill. Li Hong and Alice meet for a visit.&lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; Alice can't join Li Hong because her mother is ill. Li Hong suggests Si Leung to stay at home.&lt;/s&gt;</td>\n",
       "      <td>2.150470</td>\n",
       "      <td>1.183595</td>\n",
       "      <td>-0.966874</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>Summarize the following conversation. #Person1#: It smells like an ashtray in here! #Person2#: Hi honey! What's wrong? Why do you have that look on your face? #Person1#: What's wrong? I thought we agreed that you were gonna quit smoking. #Person2#: No! I said I was going to cut down which is very different. You can't just expect me to go cold turkey overnight! #Person1#: Look, there are other ways to quit. You can try the nicotine patch, or nicotine chewing gum. We spend a fortune on cigaret...</td>\n",
       "      <td>&lt;pad&gt; #Person1# shows #Person2# a fresh look of nervousness on #Person2#'s face. They know there's some other ways to quit but #Person2# has no idea how to quit because people spend more money on cigarettes every month, as coffee shop is on its way with the restrictions.&lt;/s&gt;</td>\n",
       "      <td>&lt;pad&gt; Holly thinks she smells like an ashtray and wants a divorce, but she knows 60 minutes take till she quits smoking.&lt;/s&gt;</td>\n",
       "      <td>2.479597</td>\n",
       "      <td>1.200324</td>\n",
       "      <td>-1.279273</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  query  \\\n",
       "0   Summarize the following conversation. #Person1#: Oh, my God! What's this? #Person2#: What? #Person1#: Look! This window is open. #Person2#: Did you open it before we left? #Person1#: Are you kidding? It's winter. Why would I open it? #Person2#: I don't know. Wait. Is this yours? #Person1#: No! Oh, my God! Someone has broken into the house. #Person2#: It looks that way. That's probably why the door wasn't locked when we came in. #Person1#: I locked it when I left though. #Person2#: Yes, but t...   \n",
       "1                                                                                                                                                                   Summarize the following conversation. #Person1#: Judy, what is everybody talking about? #Person2#: Haven't you heard? Richard was fired by our manager. #Person1#: You're kidding. It can't be true. #Person2#: Believe it or not. Everybody is talking about it in the company. #Person1#: Really? I'm surprised. #Person2#: Me too. Summary: </s>   \n",
       "2                       Summarize the following conversation. #Person1#: Mom, I just finished my paper. Can you proofread it before I hand it in? #Person2#: Sure, let's take a look. Sweetie, this is terrific. Your ideas are so original. #Person1#: Thanks. #Person2#: I can tell you worked hard on it. #Person1#: I really did! I started thinking about what I wanted to say three weeks ago. #Person2#: Well, it was definitely worth all the time. #Person1#: Let's just hope my teacher agrees. Summary: </s>   \n",
       "3                                                                                                                                                                                                                                         Summarize the following conversation. #Person1#: Could you help me, Sir? My flight got in 15 minutes ago. Everyone else has picked up the luggage but mine hasn't come through. #Person2#: I'm sorry, Madam, I'll go and find out if there is any more to come. Summary: </s>   \n",
       "4   Summarize the following conversation. #Person1#: Today more and more families have personal computers. People have wider range of choice to communicate with the outside world. #Person2#: Right. With the establishment of Internet and a lot of web companies, people are getting more and more dependent on the web. #Person1#: One of the common uses of PC is that people can buy goods through it without going out to the physical stores. #Person2#: Can you tell me how it is done? #Person1#: If a cus...   \n",
       "5   Summarize the following conversation. #Person1#: Here is the final draft of our contract. I'm glad that we have reached an agreement on almost every term in our trade. #Person2#: Yes, it seems to me we have come quite a long way. However, let me take a close look at the final draft. #Person1#: Do you have some points to bring up? #Person2#: Well, everything we've discussed seems to be here. #Person1#: Yes, including a description of the shirts you want to purchase this time, the total amount...   \n",
       "6   Summarize the following conversation. #Person1#: I would like to order some internet today. #Person2#: What kind would you like? #Person1#: What kind of internet is there? #Person2#: You can get DEL or dial-up. #Person1#: Which of those two is best? #Person2#: I would recommend DEL. #Person1#: So that one better? #Person2#: It's better because it doesn't tie up the phone. #Person1#: What do you mean by that? #Person2#: DEL isn't connected through your phone line, but dial-up is. #Person1#: S...   \n",
       "7   Summarize the following conversation. #Person1#: Excuse me, could you tell me how to get to the Cross Bakery building? #Person2#: The Cross Bakery building? Oh sure. You're actually walking in the opposite direction. #Person1#: Oh, you're kidding! I thought I was heading east. #Person2#: No, east is the other direction. To get to the Bakery, you need to turn around and go three blocks to Broadway. When you get to the intersection of Broadway and Elm, you hang a left. Go straight down that st...   \n",
       "8                                                                                     Summarize the following conversation. #Person1#: How much are you asking for this? #Person2#: I'm offering them to you at 150 yuan a piece. Is that all right? #Person1#: Is tax already included in their price? #Person2#: Yes. Our price can't be matched. #Person1#: Would you consider a volume discount? #Person2#: If you buy 1, 000 or more, you'll get a 10 % discount. #Person1#: I'll accept your offer. Summary: </s>   \n",
       "9           Summarize the following conversation. #Person1#: What can I do for you, madam? #Person2#: I'd like to buy a toy car for my son. #Person1#: How about this one? #Person2#: It looks nice. How much is it? #Person1#: They're three hundred dollars. #Person2#: Oh, I'm afraid it's too expensive. Can you show me something cheaper? #Person1#: OK, This one is one hundred and twenty. It's the cheapest here. #Person2#: OK, I'll take it. Here's the money. #Person1#: Thank you very much. Summary: </s>   \n",
       "10  Summarize the following conversation. #Person1#: Could you help me figure out how to look for a job? #Person2#: We have lots of options, what type of job do you need? #Person1#: I want to work in an office. #Person2#: Do you want to work part-time or full-time? #Person1#: I want to work full-time. #Person2#: We have binders with local job listings or you can make use of the computers. OK? #Person1#: I am confused a bit but I am sure that I can figure it out. #Person2#: If you make an appoint...   \n",
       "11  Summarize the following conversation. #Person1#: Let's take a coffee break, shall we? #Person2#: I wish I could, but I can't. #Person1#: What keeps you so busy? You've been sitting there for hours. You've got to walk around. You just can't stay on the computer forever. #Person2#: Well, I am up to my neck in work. I've got to finish this report. Sarah needs it by noon. I don't want to be scolded if I can't finish my work by the deadline. #Person1#: I understand that, but you'd feel better if ...   \n",
       "12                                                                                                                                                                                                                          Summarize the following conversation. #Person1#: Amanda, how do you like this peaked cap? #Person2#: Didn't you say you want to buy a top hat? #Person1#: But I think this one fits me Well. Why don't you try on the sombrero in black? #Person2#: I don't like caps at all. Summary: </s>   \n",
       "13  Summarize the following conversation. #Person1#: Where shall I register, please? #Person2#: Here. Do you have a registration card? #Person1#: Yes. Here you are. #Person2#: Please register your information here and pay for it. And I'll make a medical record for you. #Person1#: OK. How much do I need to pay for the registration? #Person2#: Please pay ten yuan for the registration. #Person1#: Here is my money. #Person2#: This is your registration card. Please don't lose it and bring it whenever...   \n",
       "14                                                                                                                                                                        Summarize the following conversation. #Person1#: I'd like to have this cashed, please. #Person2#: Please put you name and address here. May I see your passport? #Person1#: Yes. #Person2#: How would you like it? #Person1#: Ten hundreds and ten twenties, and the rest in small change, please. #Person2#: OK. Here you are. Summary: </s>   \n",
       "15  Summarize the following conversation. #Person1#: So how did you like the restaurant? #Person2#: Actually, it could have been better. #Person1#: What didn't you like about it? #Person2#: It is a new restaurant. I don't think they have their act together yet. #Person1#: What did you think about the food? #Person2#: I felt that the food was pretty mediocre. #Person1#: The service wasn't that great, either. #Person2#: I agree. The service was not good. #Person1#: Do you think that you want to tr...   \n",
       "16  Summarize the following conversation. #Person1#: Hello. I want to reconfirm our flight to London. #Person2#: Yes, sir. Did you call the airline? #Person1#: Yes, I did. But I couldn't communicate with them in English. They speak only Spanish. So I need your help. #Person2#: Certainly, sir. What is the flight number and when are you leaving? #Person1#: We are taking IB 385 to London tomorrow at 1 p. m. #Person2#: Oh, I see, sir. We have the airline office inside the hotel. They have an English...   \n",
       "17  Summarize the following conversation. #Person1#: I'm forming a music band. #Person2#: Do you already know how to play an instrument? #Person1#: Uh... Yeah! I'Ve told you a thousand times that I'm learning to play the drums. Now that I know how to play well, I would like to form a rock band. #Person2#: Aside from yourself, who are the other members of the band? #Person1#: We have a guy who plays guitar, and another who plays bass. Although we still haven't found anyone to be our singer. You t...   \n",
       "18  Summarize the following conversation. #Person1#: Hello? #Person2#: Hello? #Person1#: Can I speak to Li Hong, please? #Person2#: Speaking. #Person1#: Hi, Li Hong. This is Alice. #Person2#: Hi, Alice. How are you? #Person1#: Not bad. Li Hong, I am sorry that I can't go to see Mrs. Brown with you tomorrow morning. My mother is ill. I must take care of her. #Person2#: I'm sorry to hear that. You'd better stay at home. After all, we can visit Mrs. Brown later #Person1#: OK. Bye - bye. #Person2#: ...   \n",
       "19  Summarize the following conversation. #Person1#: It smells like an ashtray in here! #Person2#: Hi honey! What's wrong? Why do you have that look on your face? #Person1#: What's wrong? I thought we agreed that you were gonna quit smoking. #Person2#: No! I said I was going to cut down which is very different. You can't just expect me to go cold turkey overnight! #Person1#: Look, there are other ways to quit. You can try the nicotine patch, or nicotine chewing gum. We spend a fortune on cigaret...   \n",
       "\n",
       "                                                                                                                                                                                                                                                                                                                           response_before  \\\n",
       "0                                                                                                                                                             <pad> Allen has broken into the house and one of his things was stolen. Allen's mind stops and recognizes the only thing the robber stole. Allen will go to the windows.</s>   \n",
       "1                                                                                                                                                                                                                                <pad> Judy and her boss are surprised that Richard was fired. So, Judy and #Person2# think it's true.</s>   \n",
       "2                                                                                                                                                                            <pad> #Person1# asks #Person2# about mom's imprint essay. #Person1# got excellent ideas from #Person1#'s mom. #Person2# thinks it was worth all the time.</s>   \n",
       "3                                                                                                                                                                                                                                           <pad> #Person1# doesn't know her flight is running and she cannot get someone to help her.</s>   \n",
       "4                                     <pad> #Person1# tells #Person2# how the entire people have personal computers. After a successful test of units by a customer, #Person2# can buy goods through the computer without going to the physical stores. #Person2# tells #Person1# in detail how the computer can be used to buy goods.</s>   \n",
       "5                                                                                                              <pad> #Person2# tells #Person1# that they still have a good agreement on almost every term in their trade. #Person1# shows #Person2# the final draft with photos of every detail. #Person2# will sign the contract now.</s>   \n",
       "6                                                                                                                                                      <pad> #Person1# is buying DEL and converts #Person1#'s football to a DEL relay or dial-up internet. #Person2# thinks DEL is not connected through a phone line, but dial-up is.</s>   \n",
       "7                                                                                                        <pad> #Person1# wants to do directions to the Cross Bakery yet #Person2# tells her the opposite direction to get there. #Person1# begins at Broadway and meets the Cross Bakery building. #Person2# will show #Person1# a way</s>   \n",
       "8                                                                                                                                                                                                                  <pad> #Person1# offers to buy a cheap car new. #Person2# offers a discount if #Person1# buys more than 1,000 items.</s>   \n",
       "9                                                                                                                                                                   <pad> #Person2# wants to buy a toy car for her son. They lose it because it's too expensive. #Person1# helps to find it for her and helps #Person2# pay the price.</s>   \n",
       "10                                                                                                                                                                <pad> #Person1# asks #Person2# to help look for a job. #Person2# recommends #Person1# to see a job counselor, but #Person1# doesn't think #Person1# need to do that.</s>   \n",
       "11                                                                                                                                                                         <pad> #Person1# invites #Person2# to have a coffee break enjoying the fast pace of work, unlike #Person2# who is still too busy to do much work afterwards.</s>   \n",
       "12                                                                                                                                                                                                                                                       <pad> Amanda likes going for top hats but #Person2# doesn't want to buy caps.</s>   \n",
       "13                                                                                                                                                                                   <pad> #Person2# invites #Person1# to a clinic. #Person1# tells #Person2# the visiting hours is 11:00 GMT and #Person1# pays for the registration.</s>   \n",
       "14                                                                                                                                                                                      <pad> The cash for #Person1# was cashed with $10s and twenties in small change. #Person1# is satisfied with the cash and chooses to change it.</s>   \n",
       "15                                                                                                                                                                                                                                                        <pad> #Person1# asks #Person2# how the restaurant was and calls in a rating.</s>   \n",
       "16                                                                                                                                              <pad> #Person1# wants to confirm their flight for tomorrow at 1 p.m. #Person2# calls '35' so #Person1# can call the airline office to confirm the data. #Person1# has just dialed 135.</s>   \n",
       "17  <pad> #Person1# wants to form a rock band after learning to play the drums. #Person2# invites #Person1# to audition at #Person1#'s house this weekend, because #Person1# doesn't have enough space for the amplifiers, microphones, and even the drums. #Person1#'s music talent is enough so #Person2# can audition this weekend.</s>   \n",
       "18                                                                                                                                                                                                                 <pad> Alice can't visit Mrs. Brown tomorrow morning, because her mother is ill. Li Hong and Alice meet for a visit.</s>   \n",
       "19                                                     <pad> #Person1# shows #Person2# a fresh look of nervousness on #Person2#'s face. They know there's some other ways to quit but #Person2# has no idea how to quit because people spend more money on cigarettes every month, as coffee shop is on its way with the restrictions.</s>   \n",
       "\n",
       "                                                                                                                                                                                                                                                                             response_after  \\\n",
       "0                            <pad> Allen and #Person1# are concerned about what a robber stole, though they don't think there will be one alive. Allen had a picture of the bird but the bird locked it and made the bird flee, which he found through the door then not locked at all.</s>   \n",
       "1                                                                                                                                                             <pad> Judy and Judy understand Richard was fired. Judy is surprised because everybody is talking about it in the company.</s>   \n",
       "2                                                                                                                                                           <pad> Mother lends her a paper proofread before handing it in. It has been a hard one, but Mom shows sarcastic displeasure.</s>   \n",
       "3                                                                                                                                                                                <pad> #Person1# says everyone else has picked up the luggage but their flight got into 15 minutes ago.</s>   \n",
       "4   <pad> #Person1# shows some examples of the uses of a PC. Takes a lesson from PC for people to buy some groceries by relying on the web and connects to the sales company. She tells #Person2# how she can place an order online and enjoys the service because the deliver is free.</s>   \n",
       "5                    <pad> #Person2# has briefed #Person1# about outstanding terms and approaches the final draft. They have brought up points in the final draft. They have several days to finish their notes on the terms and defects; therefore they want to sign the contract now.</s>   \n",
       "6                                                                                     <pad> #Person2# the best Internet is DEL. It means it isn't connected beyond the phone line. Since DEL isn't connected through the phone line, it's still possible to use a phone when using DEL.</s>   \n",
       "7                                                                                                                      <pad> #Person1# asks for #Person2#'s directions and asks for the direction on which to get to the Bakery. #Person2# offers #Person1# an extended trip by subway.</s>   \n",
       "8                                                                                                                                                                  <pad> #Person1# buys a bird for 150 yuan per piece and will get 10% discount if purchase more than 1 000 of a piece.</s>   \n",
       "9                                                                                                                                                  <pad> #Person1# wants to sell a toy car for her son. #Person1# recommends one hundred and twenty dollars and offers it to #Person2#.</s>   \n",
       "10                                                                                                     <pad> #Person1# asks #Person2# about using the job center and how to find a job. #Person2# helped #Person1# with shoplifting in the same location and timely within the company.</s>   \n",
       "11                                                                                             <pad> #Person1# wants to take a coffee, but #Person2# can't take a break because he's up to his neck in work. #Person1# explained that #Person2# would feel better if they took a break.</s>   \n",
       "12                                                                                                                                                                                                     <pad> Amanda doesn't like a cap but she likes this one because it fits her well.</s>   \n",
       "13                                                                          <pad> #Person2# registers his information for the surgery for #Person1#. #Person2# wants to make a medical record and describes the terms of treatment. #Person1# will go down this way and see the doctor.</s>   \n",
       "14                                                                                                                                                                                 <pad> #Person2# is shopping for cash and helps #Person1# to get ten hundreds and ten twenties bills.</s>   \n",
       "15                                                                                                                    <pad> #Person2# loved the restaurant but it's a new one and service wasn't very good. #Person2# was angry with the restaurant because it's new and it's not good.</s>   \n",
       "16                                                                                                                                                                                      <pad> The airline can't tell #Person1# how to get the flight to London from #Person2#'s office.</s>   \n",
       "17                                                                                                            <pad> #Person1# wants to start a music band and wants to do so when he realizes there's no singer. #Person1# decides to audition but the audition is at #Person1#'s home.</s>   \n",
       "18                                                                                                                                                                                 <pad> Alice can't join Li Hong because her mother is ill. Li Hong suggests Si Leung to stay at home.</s>   \n",
       "19                                                                                                                                                             <pad> Holly thinks she smells like an ashtray and wants a divorce, but she knows 60 minutes take till she quits smoking.</s>   \n",
       "\n",
       "    reward_before  reward_after  reward_diff  \n",
       "0        1.577376      2.092901     0.515524  \n",
       "1        0.998530      1.466953     0.468423  \n",
       "2        2.231749      2.643997     0.412248  \n",
       "3        1.835569      2.229936     0.394368  \n",
       "4        2.635307      2.945903     0.310597  \n",
       "5        3.081573      3.372005     0.290432  \n",
       "6        2.184070      2.379267     0.195198  \n",
       "7        2.654602      2.839283     0.184682  \n",
       "8        2.325330      2.508447     0.183116  \n",
       "9        1.195809      1.301500     0.105691  \n",
       "10       2.113558      2.147066     0.033508  \n",
       "11       1.959802      1.826756    -0.133046  \n",
       "12       1.396727      1.256419    -0.140307  \n",
       "13       1.620430      1.424039    -0.196391  \n",
       "14       1.972783      1.769356    -0.203427  \n",
       "15       2.401509      2.186926    -0.214583  \n",
       "16       1.978626      1.759486    -0.219140  \n",
       "17       2.767497      2.376706    -0.390790  \n",
       "18       2.150470      1.183595    -0.966874  \n",
       "19       2.479597      1.200324    -1.279273  "
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.set_option('display.max_colwidth', 500)\n",
    "df_compare_results = pd.DataFrame(compare_results)\n",
    "df_compare_results[\"reward_diff\"] = df_compare_results['reward_after'] - df_compare_results['reward_before']\n",
    "df_compare_results_sorted = df_compare_results.sort_values(by=['reward_diff'], ascending=False).reset_index(drop=True)\n",
    "df_compare_results_sorted"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e7fb2477-f719-48de-b169-0607d355a8f6",
   "metadata": {},
   "source": [
    "Looking at the reward mean/median of the generated sequences you can observe a significant difference!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "df4a19dd-ef86-41a9-8937-9c1d1494ac62",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "availableInstances": [
   {
    "_defaultOrder": 0,
    "_isFastLaunch": true,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 4,
    "name": "ml.t3.medium",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 1,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.t3.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 2,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.t3.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 3,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.t3.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 4,
    "_isFastLaunch": true,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.m5.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 5,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.m5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 6,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.m5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 7,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.m5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 8,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.m5.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 9,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.m5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 10,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.m5.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 11,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.m5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 12,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.m5d.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 13,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.m5d.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 14,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.m5d.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 15,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.m5d.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 16,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.m5d.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 17,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.m5d.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 18,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.m5d.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 19,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.m5d.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 20,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": true,
    "memoryGiB": 0,
    "name": "ml.geospatial.interactive",
    "supportedImageNames": [
     "sagemaker-geospatial-v1-0"
    ],
    "vcpuNum": 0
   },
   {
    "_defaultOrder": 21,
    "_isFastLaunch": true,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 4,
    "name": "ml.c5.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 22,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.c5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 23,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.c5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 24,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.c5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 25,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 72,
    "name": "ml.c5.9xlarge",
    "vcpuNum": 36
   },
   {
    "_defaultOrder": 26,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 96,
    "name": "ml.c5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 27,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 144,
    "name": "ml.c5.18xlarge",
    "vcpuNum": 72
   },
   {
    "_defaultOrder": 28,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.c5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 29,
    "_isFastLaunch": true,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.g4dn.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 30,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.g4dn.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 31,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.g4dn.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 32,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.g4dn.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 33,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.g4dn.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 34,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.g4dn.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 35,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 61,
    "name": "ml.p3.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 36,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 244,
    "name": "ml.p3.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 37,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 488,
    "name": "ml.p3.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 38,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 768,
    "name": "ml.p3dn.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 39,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.r5.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 40,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.r5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 41,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.r5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 42,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.r5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 43,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.r5.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 44,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.r5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 45,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 512,
    "name": "ml.r5.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 46,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 768,
    "name": "ml.r5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 47,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.g5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 48,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.g5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 49,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.g5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 50,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.g5.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 51,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.g5.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 52,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.g5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 53,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.g5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 54,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 768,
    "name": "ml.g5.48xlarge",
    "vcpuNum": 192
   },
   {
    "_defaultOrder": 55,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 1152,
    "name": "ml.p4d.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 56,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 1152,
    "name": "ml.p4de.24xlarge",
    "vcpuNum": 96
   }
  ],
  "instance_type": "ml.m5.2xlarge",
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
